/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package it.pdm.mep;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import it.paint.mep.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.*;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;

import android.view.Display;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

public class FingerPaint extends Activity implements
		ColorPickerDialog.OnColorChangedListener {

	private static Bitmap mBitmap = null; // Bitmap del canvas
	Bitmap originalBitmap = null; // Bitman di partenza per disegnare il canvas
	private final static int FILE_CHOOSER_IMAGE = 49203; // Identifica la intent
															// che avvia il
															// ImageBroswe
	private Paint mPaint; // Paint
	private MaskFilter mEmboss; // Mask per creare il pennello in Rilievo
	private MaskFilter mBlur; // Mask per creare il pennello Sfocato
	private static Context context = null;
	private int sizeBrush = 12; // Dimensione del pennello, 12 di default
	static boolean saved = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		context = this;
		if (savedInstanceState != null) { // Vuol dire che non è la prima volta
											// che passa entra nello onCreate(),
											// quindi ha effettuato il passaggio
											// tra landscpe a Portrait (o il
											// contrario)
			originalBitmap = mBitmap; // Mettiamo la Bitmap che origina il
										// canvas, con quella già modificata
		}

		else { // è la prima volta che passa nella onCreate()

			originalBitmap = BitmapFactory.decodeResource(getResources(),
					R.drawable.white); // Prendiamo l'immagine bianca iniziale

		}

		setContentView(new MyView(this)); // Setto il content con MyView

		mPaint = new Paint(); // Creo il Paint
		mPaint.setAntiAlias(true); // Non smussa i contorni del disegno
		mPaint.setDither(true); // non tronca i colori
		mPaint.setColor(0xFFFF0000); // Colore di default Rosso
		mPaint.setStyle(Paint.Style.STROKE); // set lo stile della vernice
		mPaint.setStrokeJoin(Paint.Join.ROUND); // setta come viene unita la
												// vernice
		mPaint.setStrokeCap(Paint.Cap.ROUND);
		mPaint.setStrokeWidth(sizeBrush); // set il tipo di pennello

		mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6, 3.5f); // Parametri
																				// del
																				// pennello
																				// in
																				// rilievo

		mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL); // Parametri
																	// del
																	// pennello
																	// Sfocato
	}

	public void colorChanged(int color) { // Funzione che cambia il colore del
											// Paint
		mPaint.setColor(color);
	}

	public class MyView extends View { // View che sarà quella principale

		private Canvas mCanvas; // Canvas della view
		private Path mPath; // Incapsula il percorso disegnato attraverso il
							// tocco dello schermo
		private Paint mBitmapPaint; // Bitmap della view

		public MyView(Context c) {
			super(c);

			mPath = new Path(); // Inizializziamo il Path
			mBitmapPaint = new Paint(Paint.DITHER_FLAG);
		}

		@Override
		protected void onSizeChanged(int w, int h, int oldw, int oldh) { // Viene
																			// chiamata
																			// quando
																			// le
																			// dimensioni
																			// della
																			// view
																			// cambiano
			super.onSizeChanged(w, h, oldw, oldh);
			Display display = getWindowManager().getDefaultDisplay(); // Prendimo
																		// le
																		// dimensioni
																		// del
																		// Display

			mBitmap = Bitmap.createScaledBitmap(originalBitmap,
					display.getWidth(), display.getHeight(), true); // A mBitmap
																	// assegnemo
																	// originalBitmap
																	// ridimendionando
																	// l'immagine
																	// in base
																	// alla
																	// dimensione
																	// del
																	// Display

			mCanvas = new Canvas(mBitmap); // Creiamo il Canvas con la bitmap
											// ridimensionata

		}

		@Override
		protected void onDraw(Canvas canvas) { // Disegna il path sul canvas
			canvas.drawColor(0xFFAAAAAA);

			canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

			canvas.drawPath(mPath, mPaint); // Disegna sul canvas la traccia di
											// disegno effettuata dall'utente
		}

		private float mX, mY; // Cordinate del tocco
		private static final float TOUCH_TOLERANCE = 4; // Tolleranza del tocco

		private void touch_start(float x, float y) { // Viene chiamata quando
														// inizia il tocco
			mPath.reset();
			mPath.moveTo(x, y);
			mX = x;
			mY = y;
		}

		private void touch_move(float x, float y) { // Viene chiamata quando c'è
													// il trascinamento sullo
													// schermo
			float dx = Math.abs(x - mX);
			float dy = Math.abs(y - mY);
			if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
				mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
				mX = x;
				mY = y;
			}
		}

		private void touch_up() { // Viene chiamata quando l'utente finisce di
									// trascinare
			mPath.lineTo(mX, mY); // Impostiamo Il path
			mCanvas.drawPath(mPath, mPaint); // Scrive il path sullo schermo

			mPath.reset(); // resettiamo il path
		}

		@Override
		public boolean onTouchEvent(MotionEvent event) {
			float x = event.getX();
			float y = event.getY();

			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN: // Se l'evento è l'inizio del tocco
											// chiamo touch_start
				touch_start(x, y);
				invalidate(); // forza la view a disegnare
				break;
			case MotionEvent.ACTION_MOVE: // Se l'evento è il trascinamento
											// chiamo la touch_move
				touch_move(x, y);
				invalidate();
				break;
			case MotionEvent.ACTION_UP:// Se l'evento è il rilascio chiamo la
										// touch_up
				touch_up();
				invalidate();
				break;
			}
			return true;
		}
	}

	private static final int COLOR_MENU_ID = R.id.color; // Id del Button color
															// nel menu

	private static final int ERASE_MENU_ID = R.id.erase; // Id del Button erase
															// nel menu
	private static final int ERASE_ALL = R.id.eraseall; // Id del Button
														// eraseall nel menu
	private static final int BRUSH_MENU_ID = R.id.brush; // Id del Button brush
															// nel menu
	private static final int SAVE_MENU_ID = R.id.save; // Id del Button save nel
														// menu
	private static final int OPEN_MENU_ID = R.id.open; // Id del Button open nel
														// menu

	private static final int NORMAL_Radio_ID = R.id.radioNormal; // Id del
																	// RadioButton
																	// nel
																	// dialog
																	// pennelloNormale
	private static final int EMBOSS_Radio_ID = R.id.radioEmboss;// Id del
																// RadioButton
																// nel dialog
																// pennelloRialzato
	private static final int BLUR_Radio_ID = R.id.radioBlur; // Id del
																// RadioButton
																// nel dialog
																// pennelloSfocato

	@Override
	public boolean onCreateOptionsMenu(Menu menu) { // Assegniamo al menu il
													// layout
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		super.onPrepareOptionsMenu(menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) { // Quando viene aperto
															// il menu
		mPaint.setXfermode(null);
		mPaint.setAlpha(0xFF);

		switch (item.getItemId()) {
		case COLOR_MENU_ID:
			new ColorPickerDialog(this, this, mPaint.getColor()).show(); // Se
																			// clicca
																			// sul
																			// button
																			// del
																			// colore
																			// si
																			// apre
																			// il
																			// dialog
																			// per
																			// la
																			// scelta
																			// del
																			// colore
			return true;

		case ERASE_MENU_ID:
			mPaint.setColor(Color.WHITE); // se clicca il bottone Gomma settiamo
											// il colore del pennello Bianco
			mPaint.setMaskFilter(null); // Settiamo il tipo di pennello in
										// normale
			return true;

		case BRUSH_MENU_ID: { // In caso del Button pennello
			final Dialog dialog1 = new Dialog(FingerPaint.this); // Creo una
																	// finestra
																	// di
																	// dialogo
			dialog1.setContentView(R.layout.brush_dialog); // Imposto il layout
															// del dialog con
															// uno creato in
															// precedenza
			dialog1.setTitle(getString(R.string.modify_brush)); // Setto il
																// titolo della
																// finestra
			dialog1.setCancelable(true); // L'utente può uscire dalla finestra
			dialog1.show(); // Mostriamo la finestra
			final SeekBar seekBrush = (SeekBar) dialog1 // Prendiamo le varie
														// View dalla finestra
					.findViewById(R.id.brushBar); // SeekBar che permette
													// all'utente di scegliere
													// la dimensione del
													// pennello
			final TextView seekValue = (TextView) dialog1
					.findViewById(R.id.seekValue);
			final RadioGroup radio = (RadioGroup) dialog1
					.findViewById(R.id.radioBrushType);

			seekBrush.setMax(25); // Settiamo il livello massiamo della seekBar
									// a 25
			seekBrush.setProgress(sizeBrush); // setto la seakBar alla
												// dimenzione del pennello
			seekValue.setText("" + sizeBrush); // Settiamo la

			Button buttonOKBrush = (Button) dialog1.findViewById(R.id.bOKBrush); // Se
																					// l'utente
																					// clicca
																					// su
																					// annulla
																					// chiudiamo
																					// la
																					// finestra
																					// di
																					// dialog
			seekBrush.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { // Quando
																					// la
																					// seekBAr
																					// viene
																					// mossa
																					// facciamo
																					// vedere
																					// il
																					// valore
																					// che
																					// ha

						@Override
						public void onStopTrackingTouch(SeekBar seekBar) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onStartTrackingTouch(SeekBar seekBar) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onProgressChanged(SeekBar seekBar,
								int progress, boolean fromUser) {

							seekValue.setText("" + seekBrush.getProgress());

						}
					});
			buttonOKBrush.setOnClickListener(new OnClickListener() { // Quando
																		// l'utente
																		// clicca
																		// Ok
																		// sulla
																		// finestra
																		// di
																		// dialogo
																		// vediamo
																		// cosa
																		// ha
																		// scelto
						@Override
						public void onClick(View v) {
							sizeBrush = seekBrush.getProgress();
							mPaint.setStrokeWidth(sizeBrush); // Settiamo la
																// dimensione
																// del pennello
																// con quella
																// scelta
							if (radio.getCheckedRadioButtonId() == NORMAL_Radio_ID) { // Se
																						// seleziona
																						// il
																						// pennello
																						// normale
																						// lo
																						// settiamo
																						// in
																						// Normale
								mPaint.setMaskFilter(null);
							} else if (radio.getCheckedRadioButtonId() == BLUR_Radio_ID) {// Se
																							// seleziona
																							// il
																							// pennello
																							// sfocato
																							// lo
																							// settiamo
																							// in
																							// Sfocato
								mPaint.setMaskFilter(mBlur);

							} else if (radio.getCheckedRadioButtonId() == EMBOSS_Radio_ID) {// Se
																							// seleziona
																							// il
																							// pennello
																							// Rilievo
																							// lo
																							// settiamo
																							// in
																							// Rilievo
								mPaint.setMaskFilter(mEmboss);

							}

							dialog1.dismiss(); // Chiudiamo la finestra di
												// dialogo
						}
					});

			return true;
		}
		case ERASE_ALL: // Se clicca sul Button erase all cancelliamo tutto,
						// quindi rimpostiamo la Bitmap con quella bianca,
						// iniziale
			AlertDialog alertDialog = new AlertDialog.Builder(FingerPaint.this) // Messaggio
																				// di
																				// conferma
					.create();
			alertDialog.setTitle(getString(R.string.Warning));
			alertDialog.setMessage(getString(R.string.EraseProgress));
			alertDialog.setIcon(R.drawable.warning);
			alertDialog.setButton(getString(R.string.OK),
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {

							Display display = getWindowManager()
									.getDefaultDisplay();
							Bitmap tempBitmap = BitmapFactory.decodeResource(
									getResources(), R.drawable.white);
							originalBitmap = Bitmap.createScaledBitmap(
									tempBitmap, display.getWidth(),
									display.getHeight(), true);
							setContentView(new MyView(context));

						}
					});
			alertDialog.setButton2(getString(R.string.Annulla),
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {

						}
					});
			alertDialog.show(); // Mostriamo il messaggio

			return true;
		case OPEN_MENU_ID: // Se clicca sull'Open apriamo l'intent che ci
							// permette di sfogliare l'immagini del dispositivo

			Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
			intent.setType("image/*");
			startActivityForResult(intent, FILE_CHOOSER_IMAGE);
			return true;
		case SAVE_MENU_ID: // Se clicca sul Button Salva apriamo un dialog che
							// ci permette di scegliere il nome da dare
							// all'immagine

			final Dialog saveDialog = new Dialog(FingerPaint.this);
			saveDialog.setContentView(R.layout.save_dialog);
			saveDialog.setTitle(getString(R.string.SaveWithName));
			saveDialog.setCancelable(true);
			saveDialog.show();
			final EditText fileName = (EditText) saveDialog
					.findViewById(R.id.filename_field);
			Button saveButton = (Button) saveDialog
					.findViewById(R.id.save_img_button);
			Button cancelButton = (Button) saveDialog
					.findViewById(R.id.cancel_img_button);

			saveButton.setOnClickListener(new OnClickListener() { // Se clicca
						// sul
						// Button
						// Salva del
						// dialog a
						// quel
						// punto
						// salviamo
						// l'immagine
						@Override
						public void onClick(View v) {
							try {
								File file = null;
								FileOutputStream fos = null;
								String state = Environment
										.getExternalStorageState();
								if (Environment.MEDIA_MOUNTED.equals(state)) {
									String name=fileName.getText()
											.toString();
									if(name==null || name.equals("")){
										saveDialog.dismiss();
										AlertDialog alertDialog = new AlertDialog.Builder(FingerPaint.this) //Messaggio se il nome del file che ha inserito l'utente è vuoto
										.create();
								alertDialog.setTitle(getString(R.string.Warning));
								alertDialog.setMessage(getString(R.string.NameFile));
								alertDialog.setIcon(R.drawable.warning);
								alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
									public void onClick(DialogInterface dialog, int which) {

										// Al click di Ok non devo fare niente, quindi lo lasciamo vuoto

									}
								});

								alertDialog.show(); // Mostriamo il messaggio
									}else{
									String filename = name + ".png";
									File sdCard = Environment
											.getExternalStorageDirectory();
									File dir = new File(sdCard
											.getAbsolutePath() + "/MEPaint"); // Salviamo
																				// L'immagine
																				// nella
																				// sdCard
									dir.mkdirs();
									file = new File(dir, filename);
									if (file.exists()) { // Se l'immagine esiste chiediamo all'utente se vuole sovrascriverla
										AlertDialog alertDialogSave = new AlertDialog.Builder(
												FingerPaint.this) // Messaggio
																	// di
																	// conferma
												.create();
										alertDialogSave
												.setTitle(getString(R.string.Warning));
										alertDialogSave
												.setMessage(getString(R.string.ImmagineEsistente));
										alertDialogSave
												.setIcon(R.drawable.warning);
										alertDialogSave
												.setButton(
														getString(R.string.OK),
														new DialogInterface.OnClickListener() { //Se clicca su "Ok" la salviamo
															public void onClick(
																	DialogInterface dialog,
																	int which) {

																File file = null;
																FileOutputStream fos = null;
																String state = Environment
																		.getExternalStorageState();
																if (Environment.MEDIA_MOUNTED
																		.equals(state)) {
																	String filename = fileName
																			.getText()
																			.toString()
																			+ ".png";
																	File sdCard = Environment
																			.getExternalStorageDirectory();
																	File dir = new File(
																			sdCard.getAbsolutePath()
																					+ "/MEPaint"); // Salviamo
																									// L'immagine
																									// nella
																									// sdCard
																	dir.mkdirs();
																	file = new File(
																			dir,
																			filename);
																	try {
																		fos = new FileOutputStream(
																				file);
																	} catch (FileNotFoundException e) {
																		// TODO
																		// Auto-generated
																		// catch
																		// block
																		e.printStackTrace();
																	}
																	mBitmap.compress(
																			Bitmap.CompressFormat.PNG,
																			90,
																			fos);
																	try {
																		fos.close();
																	} catch (IOException e) {
																		// TODO
																		// Auto-generated
																		// catch
																		// block
																		e.printStackTrace();
																	}
																	sendBroadcast(new Intent( // Montiamo
																								// la
																								// memoria
																								// altrimenti
																								// il
																								// dispositivo
																								// ci
																								// farebbe
																								// vedere
																								// l'immagine
																								// salvata
																								// solo
																								// al
																								// riavvio
																								// del
																								// dispositivo
																			Intent.ACTION_MEDIA_MOUNTED,
																			Uri.parse("file://"
																					+ Environment
																							.getExternalStorageDirectory())));

																	showSavedToast(true);
																}

															}
														});
										alertDialogSave
												.setButton2(
														getString(R.string.Annulla), 
														new DialogInterface.OnClickListener() { //se clicca su "annulla" non facciamo niente e mostriamo un toast di avviso
															public void onClick(
																	DialogInterface dialog,
																	int which) {
																showSavedToast(false);

															}
														});
										alertDialogSave.show(); // Mostriamo il
																// messaggio

									} else {

										fos = new FileOutputStream(file);
										mBitmap.compress(
												Bitmap.CompressFormat.PNG, 90,
												fos);
										fos.close();
										sendBroadcast(new Intent( // Montiamo la
																	// memoria
																	// altrimenti
																	// il
																	// dispositivo
																	// ci
																	// farebbe
																	// vedere
																	// l'immagine
																	// salvata
																	// solo al
																	// riavvio
																	// del
																	// dispositivo
												Intent.ACTION_MEDIA_MOUNTED,
												Uri.parse("file://"
														+ Environment
																.getExternalStorageDirectory())));

										showSavedToast(true);

									}
								}
								}
							} catch (Exception e) {
								e.printStackTrace();
							} finally {
								saveDialog.dismiss();
							}

						}
					});

			cancelButton.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					saveDialog.dismiss();
				}
			});
			
			return true;
			
		}
		return super.onOptionsItemSelected(item);
	}
	

	private void showSavedToast(boolean saved) {
		if (saved) {
			Toast toast = Toast.makeText(FingerPaint.this,
					getString(R.string.ImmagineSalvataCorrettamente),
					Toast.LENGTH_SHORT);
			toast.show();
		} else {
			Toast toast = Toast.makeText(FingerPaint.this,
					getString(R.string.ImmagineNonSalvata),
					Toast.LENGTH_SHORT);
			toast.show();
		}
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case FILE_CHOOSER_IMAGE: // prendiamo il risultato della intent,
										// quindi impostiamo l'immagine scelta
										// nella View
				String imagePath = getRealPathFromURI(data.getData());

				File imgFile = new File(imagePath);
				if (imgFile.exists()) {

					originalBitmap = BitmapFactory.decodeFile(imgFile
							.getAbsolutePath());

					setContentView(new MyView(this));

				}
				break;

			}

		}

	}

	public String getRealPathFromURI(Uri contentUri) { // Metodo che mi permette
														// di avere il path
														// reale passandogli
														// quello ritornato
														// dalla intent
		String[] proj = { MediaStore.Images.Media.DATA };
		Cursor cursor = managedQuery(contentUri, proj, null, null, null);
		int column_index = cursor
				.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
		cursor.moveToFirst();
		return cursor.getString(column_index);
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		super.onSaveInstanceState(outState);

		outState.putString("Rotation", "yes"); // Passimo un parametro affinchè
												// l'onCreate capisca che c'è
												// stata una rotazione del
												// dispositivo

	}

}